﻿/*
   Copyright 2012 Dmitry Bratus

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Flower.Services.Data
{
    /// <summary>
    /// Base type for directory entries.
    /// 
    /// Each derived class of this calss except DirectoryEntryInfo corresponds to
    /// a type of the entries. The DirectoryEntryInfo is used when it is required to
    /// enumerate entries without loading their payload, so the directory service provides
    /// methods returning the entries with and without payload.
    /// </summary>
    [DataContract(Namespace = XmlNamespace.Directory)]
    [KnownType(typeof(Assembly))]
    [KnownType(typeof(Folder))]
    [KnownType(typeof(Link))]
    [KnownType(typeof(Message))]
    [KnownType(typeof(Process))]
    [KnownType(typeof(Processor))]
    [KnownType(typeof(Role))]
    [KnownType(typeof(ServiceContainer))]
    [KnownType(typeof(Set))]
    [KnownType(typeof(State))]
    [KnownType(typeof(Workflow))]
    [KnownType(typeof(DirectoryEntryInfo))]
    public abstract class DirectoryEntry
    {
        /// <summary>
        /// Id of the entry.
        /// </summary>
        [DataMember]
        public string Id { get; set; }

        /// <summary>
        /// Name of the entry. 
        /// 
        /// The name must consist of only letters, digits or the following chars '#', '-', '_', '.', ':'.
        /// </summary>
        [DataMember]
        public string Name { get; set; }

        /// <summary>
        /// When the entry was created in the directory.
        /// 
        /// The property is populated if the entry is loaded from the directory; if a client
        /// creates or updates an entry, the directory ignores the property.
        /// </summary>
        [DataMember]
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// When the entry was updated in the directory last time.
        /// 
        /// The property is populated if the entry is loaded from the directory; if a client
        /// creates or updates an entry, the directory ignores the property.
        /// </summary>
        [DataMember]
        public DateTime UpdatedOn { get; set; }

        /// <summary>
        /// Access control list of the entry. When the entry is updated, the specified list
        /// overwrites the current list in the directory.
        /// </summary>
        [DataMember]
        public ICollection<AccessControlEntry> AccessControlList { get; set; }

        /// <summary>
        /// The default constructor.
        /// </summary>
        protected DirectoryEntry()
        {
            AccessControlList = new List<AccessControlEntry>();
        }

        /// <summary>
        /// Deserialization handler.
        /// </summary>
        /// <param name="context">The streaming context.</param>
        [OnDeserialized]
        protected void OnDeserialized(StreamingContext context)
        {
            if (AccessControlList == null)
            {
                AccessControlList = new List<AccessControlEntry>();
            }
        }

        /// <summary>
        /// Visitor support.
        /// </summary>
        /// <param name="visitor">Object to visit.</param>
        public abstract void AcceptVisitor(IDirectoryEntryVisitor visitor);
    }
}
